<?php

namespace App\Services;

use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;
use Illuminate\Support\Facades\Log;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;

/**
 * @see https://wiki.swoole.com/#/start/start_ws_server
 */
class WebSocketService implements WebSocketHandlerInterface
{
    /**@var \Swoole\Table $wsTable */
    private $wsTable;

    // 声明没有参数的构造函数
    public function __construct()
    {
        $this->wsTable = app('swoole')->wsTable;
    }
    // public function onHandShake(Request $request, Response $response)
    // {
    // 自定义握手：https://wiki.swoole.com/#/websocket_server?id=onhandshake
    // 成功握手之后会自动触发onOpen事件
    // }
    public function onOpen(Server $server, Request $request)
    {
        var_dump(app('swoole') === $server);// 同一实例
        // 在触发onOpen事件之前，建立WebSocket的HTTP请求已经经过了Laravel的路由，
        // 所以Laravel的Request、Auth等信息是可读的，Session是可读写的，但仅限在onOpen事件中。
        // \Log::info('New WebSocket connection', [$request->fd, request()->all(), session()->getId(), session('xxx'), session(['yyy' => time()])]);
        // 此处抛出的异常会被上层捕获并记录到Swoole日志，开发者需要手动try/catch
        dump($request->fd, request()->all(), session()->getId(), $server->getClientInfo($request->fd));
        $server->push($request->fd, $this->echoTypeMessage(['type' => 'welcome', 'message' => 'Welcome to LaravelS']));
    }

    private function echoTypeMessage(array $data = [])
    {
        return json_encode(['type' => $data['type'], 'data' => $data['data'] ?? [], 'message' => $data['message'] ?? '', 'time' => date('Y-m-d H:i:s')]);
    }

    public function onMessage(Server $server, Frame $frame)
    {
        Log::info('Received message', [$frame->fd, $frame->data, $frame->opcode, $frame->finish]);
        // 此处抛出的异常会被上层捕获并记录到Swoole日志，开发者需要手动try/catch
        $msg = $this->analysisType($frame->data);

        $server->push($frame->fd, $this->echoTypeMessage($msg));
    }

    private function analysisType($data)
    {
        if (empty($data)) {
            return ['type' => 'error', 'message' => 'data is empty'];
        }
        if (is_string($data)) {
            $data = json_decode($data, true);
            if (empty($data)) {
                return ['type' => 'error', 'message' => 'data is not json'];
            }
            if (!isset($data['type'])) {
                return ['type' => 'error', 'message' => 'type is not set'];
            }
            dump($data['type']);
            switch ($data['type']) {
                case 'message':
                    return ['type' => 'message', 'data' => $data['data'], 'msg' => $data['message'], 'time' => date('Y-m-d H:i:s')];
                    break;
                case 'error':
                    return ['type' => 'error', 'message' => $data['message']];
                    break;
                case 'getStatistics'://统计数据
                    $getStatistics = (new WebsocketDataService())->getStatistics();
                    return ['type' => 'getStatistics', 'data' => $getStatistics, 'message' => 'getStatistics'];
                    break;
                case 'getProjectTop'://销冠排行
                    $getProjectTop = (new WebsocketDataService())->getProjectTop();
                    return ['type' => 'getProjectTop', 'data' => $getProjectTop, 'message' => 'getProjectTop'];
                    break;
                case 'getProjectProgress'://最新项目30个
                    $getProjectProgress = (new WebsocketDataService())->getProjectProgress();
                    return ['type' => 'getProjectProgress', 'data' => $getProjectProgress, 'message' => 'getProjectProgress'];
                    break;
                case 'Region'://按客户地区统计项目金额
                    $getStatisticsByRegion = (new WebsocketDataService())->getStatisticsByRegion();
                    return ['type' => 'Region', 'data' => $getStatisticsByRegion, 'message' => 'Region'];
                    break;
                case 'projectManth':
                    $getProjectMCount = (new WebsocketDataService())->getProjectMCount();
                    return ['type' => 'projectManth', 'data' => $getProjectMCount, 'message' => 'projectManth'];
                    break;
                case 'test':
                    return ['type' => 'test', 'data' => $data, 'message' => 'test'];
                case 'webconfig':
                    $config = (new WebsocketDataService())->webConfig();
                    return ['type' => 'webconfig', 'data' => $config, 'message' => 'webconfig'];
                default:
                    return ['type' => 'error', 'message' => 'type is not exist'];
            }
        } else {
            return ['type' => 'error', 'message' => 'data is not array'];
        }

    }

    public function onClose(Server $server, $fd, $reactorId)
    {
        // 此处抛出的异常会被上层捕获并记录到Swoole日志，开发者需要手动try/catch
        Log::info('WebSocket connection closed', [$fd, $reactorId]);
        $server->push($fd, 'Goodbye');

    }
}
